import random
import pygame
from constants import *

class Tetris:
    def __init__(self):
        self.board = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
        self.reset()
        # 添加动画相关属性
        self.clearing_lines = []  # 正在消除的行
        self.animation_frame = 0  # 动画帧计数
        self.animation_speed = 5  # 动画速度
        self.is_animating = False  # 是否正在动画中
        self.renderer = None  # 渲染器引用，用于触发粒子效果
        
    def reset(self):
        """重置游戏状态"""
        self.board = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
        self.current_piece = self.new_piece()
        self.next_piece = self.new_piece()
        self.game_over = False
        self.paused = False
        self.score = 0
        self.level = 1
        self.lines = 0
        self.lines_cleared = 0  # 保持兼容性
        self.fall_speed = INITIAL_FALL_SPEED
        self.last_fall_time = pygame.time.get_ticks()
        self.clearing_lines = []
        self.animation_frame = 0
        self.is_animating = False
    
    def new_piece(self):
        """生成新的游戏方块"""
        shape_idx = random.randint(0, len(SHAPES) - 1)
        shape = SHAPES[shape_idx]
        color = SHAPE_COLORS[shape_idx]
        x = GRID_WIDTH // 2 - len(shape[0]) // 2
        y = 0
        return {"shape": shape, "color": color, "x": x, "y": y, "board": self.board}
    
    def valid_position(self, piece, x=None, y=None, shape=None):
        """检查方块位置是否有效"""
        if x is None:
            x = piece["x"]
        if y is None:
            y = piece["y"]
        if shape is None:
            shape = piece["shape"]
        
        for i in range(len(shape)):
            for j in range(len(shape[i])):
                if shape[i][j] == 1:
                    pos_x = x + j
                    pos_y = y + i
                    # 检查边界
                    if pos_x < 0 or pos_x >= GRID_WIDTH or pos_y >= GRID_HEIGHT:
                        return False
                    # 检查是否与已有方块重叠（忽略顶部边界外的部分）
                    if pos_y >= 0 and self.board[pos_y][pos_x] != 0:
                        return False
        return True
    
    def merge_piece(self):
        """将当前方块合并到游戏板上"""
        shape = self.current_piece["shape"]
        color = self.current_piece["color"]
        x = self.current_piece["x"]
        y = self.current_piece["y"]
        
        for i in range(len(shape)):
            for j in range(len(shape[i])):
                if shape[i][j] == 1:
                    pos_y = y + i
                    pos_x = x + j
                    if pos_y >= 0:
                        self.board[pos_y][pos_x] = color
    
    def clear_lines(self):
        """消除完整的行并更新分数和等级"""
        lines_to_clear = []
        i = GRID_HEIGHT - 1
        while i >= 0:
            if all(cell != 0 for cell in self.board[i]):
                lines_to_clear.append(i)
            i -= 1
        
        if lines_to_clear:
            # 开始行消除动画
            self.clearing_lines = lines_to_clear
            self.is_animating = True
            self.animation_frame = 0
            return len(lines_to_clear)
        return 0
        
    def update_animation(self):
        """更新行消除动画"""
        if not self.is_animating:
            return
            
        self.animation_frame += 1
        
        # 动画完成
        if self.animation_frame >= self.animation_speed:
            # 移除标记的行
            for i in sorted(self.clearing_lines, reverse=True):
                del self.board[i]
                # 在顶部添加一个空行
                self.board.insert(0, [0 for _ in range(GRID_WIDTH)])
            
            # 根据消除的行数增加分数
            lines_cleared = len(self.clearing_lines)
            if lines_cleared == 1:
                self.score += SINGLE_LINE_SCORE * self.level
            elif lines_cleared == 2:
                self.score += DOUBLE_LINE_SCORE * self.level
            elif lines_cleared == 3:
                self.score += TRIPLE_LINE_SCORE * self.level
            elif lines_cleared == 4:
                self.score += TETRIS_SCORE * self.level
            
            self.lines += lines_cleared
            self.lines_cleared = self.lines  # 保持变量名一致
            
            # 根据消除行数调整等级和速度
            self.update_level()
            
            # 重置动画状态
            self.clearing_lines = []
            self.is_animating = False
            self.animation_frame = 0
            
            # 触发粒子效果（如果有renderer实例）
            if hasattr(self, 'renderer') and self.renderer:
                # 在消除的行位置创建粒子效果
                for row in self.clearing_lines:
                    for col in range(GRID_WIDTH):
                        x = GRID_SIZE * (col + 0.5) + self.renderer.game_area_x
                        y = 50 + GRID_SIZE * (row + 0.5)
                        # 使用随机颜色创建粒子
                        color = (random.randint(200, 255), random.randint(200, 255), random.randint(255, 255))
                        self.renderer.add_particles(x, y, color, 3)
            
    def get_board_for_rendering(self):
        """获取用于渲染的棋盘数据，考虑动画效果"""
        if not self.is_animating:
            return self.board
            
        # 创建临时棋盘用于动画渲染
        temp_board = [row[:] for row in self.board]
        
        # 根据动画帧修改正在消除的行
        blink_rate = 2
        if self.animation_frame % blink_rate == 0:
            for row in self.clearing_lines:
                for col in range(GRID_WIDTH):
                    # 闪烁效果
                    if temp_board[row][col] != 0:
                        # 反转颜色为亮色
                        color = temp_board[row][col]
                        temp_board[row][col] = (min(color[0] + 100, 255), 
                                              min(color[1] + 100, 255), 
                                              min(color[2] + 100, 255))
        
        return temp_board
    
    def update_level(self):
        """更新游戏等级和下落速度"""
        new_level = self.lines // LINES_PER_LEVEL + 1
        if new_level > self.level:
            self.level = new_level
            self.fall_speed = max(MIN_FALL_SPEED, INITIAL_FALL_SPEED - (self.level - 1) * SPEED_INCREASE_RATE)
    
    def rotate_piece(self):
        """旋转当前方块"""
        shape = self.current_piece["shape"]
        # 旋转矩阵
        rotated_shape = [[shape[j][i] for j in range(len(shape) - 1, -1, -1)] for i in range(len(shape[0]))]
        
        if self.valid_position(self.current_piece, shape=rotated_shape):
            self.current_piece["shape"] = rotated_shape
    
    def move(self, dx, dy):
        """移动方块，返回是否成功移动"""
        if self.valid_position(self.current_piece, x=self.current_piece["x"] + dx, y=self.current_piece["y"] + dy):
            self.current_piece["x"] += dx
            self.current_piece["y"] += dy
            return True
        return False
    
    def drop_down(self):
        """方块自然下落"""
        if not self.move(0, 1):
            self.merge_piece()
            self.clear_lines()
            self.current_piece = self.next_piece
            self.next_piece = self.new_piece()
            # 检查游戏是否结束
            if not self.valid_position(self.current_piece):
                self.game_over = True
    
    def hard_drop(self):
        """方块直接下落到最底部"""
        # 计算可以下落的格数
        drop_distance = 0
        while self.valid_position(self.current_piece, y=self.current_piece["y"] + drop_distance + 1):
            drop_distance += 1
        
        # 移动方块到底部
        self.current_piece["y"] += drop_distance
        self.drop_down()
        
        # 硬降加分
        self.score += HARD_DROP_SCORE * drop_distance * self.level
    
    def soft_drop(self):
        """方块加速下落"""
        if self.move(0, 1):
            self.score += SOFT_DROP_SCORE * self.level
            return True
        return False
    
    def update(self):
        """更新游戏状态"""
        if self.paused or self.game_over:
            return
        
        # 先更新动画
        if self.is_animating:
            self.update_animation()
        else:
            # 只有在没有动画时才处理方块下落
            current_time = pygame.time.get_ticks()
            if current_time - self.last_fall_time > self.fall_speed * 1000:
                self.drop_down()
                self.last_fall_time = current_time